/*
 * system.c
 *
 * define some system APIs
 *
 * Copyright (C) 2022 Microwell, Inc.
 * Subject to the GNU Public License, version 2.
 *
 * Author: guoming<guoming@microwell.net>
 */
#include "system.h"
#include "core.h"

static uint8_t irq_cnt;

void sys_init(void)
{
#if (CONFIG_SCLK_SRC != SYS_LORC_FREQ && CONFIG_SCLK_SRC != SYS_HIRC_FREQ)
    #error ("CONFIG_SCLK_SRC is invalid!")
#endif

#if (CONFIG_SCLK_SRC == SYS_HIRC_FREQ)      /* HIRC, 12MHz */
    /* wait cycle, TODO; src and div, order, todo */
    SET_BIT(CLKCON0, SCLKSRC_BIT);
    #if (CONFIG_SCLK_DIV == CLK_DIV_1)
        MODIFY_REG(CKCON, CLR_WAIT, WAIT_3_CYCLE);
    #elif (CONFIG_SCLK_DIV == CLK_DIV_2)
        /* sclk div is 2, wait cycle is 1, 3MHz */
        MODIFY_REG(CLKCON0, SCLKDIV_CLR, SCLKDIV_2);
        MODIFY_REG(CKCON, CLR_WAIT, WAIT_1_CYCLE);
    #elif (CONFIG_SCLK_DIV == CLK_DIV_3)
        /* wait cycle is 0, 4MHz */
        MODIFY_REG(CLKCON0, SCLKDIV_CLR, SCLKDIV_3);
        CLEAR_BIT(CKCON, CLR_WAIT);
    #elif (CONFIG_SCLK_DIV == CLK_DIV_4)
        /* wait cycle is 0, 3MHz */
        MODIFY_REG(CLKCON0, SCLKDIV_CLR, SCLKDIV_4);
        CLEAR_BIT(CKCON, CLR_WAIT);
    #elif (CONFIG_SCLK_DIV == CLK_DIV_8)
        /* wait cycle is 0, 12/8 MHz */
        MODIFY_REG(CLKCON0, SCLKDIV_CLR, SCLKDIV_8);
        CLEAR_BIT(CKCON, CLR_WAIT);
    #elif (CONFIG_SCLK_DIV == CLK_DIV_16)
        /* wait cycle is 0, 12/16 MHz */
        MODIFY_REG(CLKCON0, SCLKDIV_CLR, SCLKDIV_16);
        CLEAR_BIT(CKCON, CLR_WAIT);
    #elif (CONFIG_SCLK_DIV == CLK_DIV_32)
        /* wait cycle is 0, 12/32 MHz */
        MODIFY_REG(CLKCON0, SCLKDIV_CLR, SCLKDIV_32);
        CLEAR_BIT(CKCON, CLR_WAIT);
    #elif (CONFIG_SCLK_DIV == CLK_DIV_64)
        /* wait cycle is 0, 12/64 MHz */
        MODIFY_REG(CLKCON0, SCLKDIV_CLR, SCLKDIV_64);
        CLEAR_BIT(CKCON, CLR_WAIT);
    #else
        #error("CONFIG_SCLK_DIV is invalid!")
    #endif
#else
    /* LORC, 32KHz */
    MODIFY_REG(CLKCON0, SCLKDIV_CLR, SCLKSRC_BIT);
    CLEAR_BIT(CKCON, CLR_WAIT);      /* wait_cycle = 0, 32KHz */
#endif
    /* delay 1ms wait SCLK stable */
    sys_delay_ms(1);

#if (CONFIG_USING_CHARGER == 1 || ADC_CHANNEL_MODE)
    MODIFY_REG(CLKCON1, ACC_CE, ACC_CE);
#elif ((CONFIG_USING_CHARGER == 1 || ADC_CHANNEL_MODE) && CMP_CHANNEL_MODE)
    MODIFY_REG(CLKCON1, (ACC_CE | CMP_CE), (ACC_CE | CMP_CE));
#endif

    /* disable the default pull-down in P05/P06 */
    CLEAR_BIT(P0PD, 0x60);
    // P0PD &= ~(0x3 << 5);
    
    /** init irq cnt **/
    irq_cnt = 1;
}

void sys_delay_10us(uint16_t us10)
{
    uint8_t delay;
    
#if (SYS_SCLK_FREQ == SYS_4MHz_FREQ)

    do {
        delay = 2;
        while(--delay);
    } while(--us10);
#elif (SYS_SCLK_FREQ == SYS_12MHz_FREQ)
    while (us10--) {
        delay = 13;
        while (delay--);
    }
#endif
}

/* 3MHZ
 * delay = 176
 * 4MHZ
 * delay = 236
 */
void sys_delay_ms(uint16_t ms)
{
    uint16_t delay;
#if (SYS_SCLK_FREQ == SYS_4MHz_FREQ)
    while (ms--) {
        delay = 236;
        while (delay--);
    }
#elif (SYS_SCLK_FREQ == SYS_12MHz_FREQ)
    while (ms--) {
        delay = 270;
        while (delay--);
    }
#endif
}

/* 
 * 12MHZ
 * 100us = 131cnt
 * 50us = 65cnt
 * 4MHZ
 * 100us = 128cnt
 * 50us = 61cnt
 * 3MHZ
 * 100us = 95cnt
 * 50us = 46cnt
 */
void sys_delay_cnt2us (uint8_t cnt)
{
    while (--cnt);
}

uint8_t sys_get_version(void)
{
    return ((RCCON >> 4) & 0x0F);
}

void irq_enable(void) 
{
    irq_cnt --;
    if(irq_cnt == 0)
        EA = 1;
}

void irq_disable(void) 
{
    EA = 0;
    irq_cnt ++;
}